Глава 16
КЛАССЫ ОБЩЕГО НАЗНАЧЕНИЯ
В состав Delphi входит около 400 различных стандартных классов, простое перечисление которых заняло бы несколько страниц книги. В этой главе рассматриваются лишь некоторые самые важные классы общего назначения.
16.1. КЛАСС EXCEPTION - ОБРАБОТКА ИСКЛЮЧЕНИЙ
Класс Exception является прямым потомком базового класса тоь-ject. Вместе со своими потомками он предназначен для обработки исключительных ситуаций (исключений), возникающих при некорректных действиях программы: например, в случае деления на ноль, при попытке открыть несуществующий файл, при выходе за пределы выделенной области динамической памяти и т. п. В этом разделе рассматриваются основные свойства исключений и их использование для повышения надежности программ.
При работе в среде Delphi эксперименты с исключениями плохо прослеживаются, т. к. при каждом исключении среда; перехватывает управление программой. В этом случае бывает полезно отменить такое поведение среды. Для этого вызовите опцию Tools. [.- -Debugger Options и на странице Languaqe Exception уберите флажок в переключателе Stop on delphi. Exceptions (для шэсдьиуш-лх версий Delphi выберите опцию меню Tools | Environent: Options и на странице Preference уберите флажок в персключателе Break on exception).
16.1.1. Защищенные блоки
Для обработки исключений в Object Pascal предусмотрен механизм защищенного блока:
except <обработчики исключений> else <операторы> end; |
finally <операторы> end; |
Try <операторы> |
Try <операторы> |
Защищенный блок начинается зарезервированным словом try (попытаться [выполнить]) и завершается словом end. Существуют два типа защищенных блоков - except (исключить) и finally (в завершение), отличающихся способом обработки исключения. В блоке except порядок выполнения операторов таков: сначала выполняются операторы секции try... except; если операторы выполнены без возникновения исключительной ситуации, работа защищенного блока на этом прекращается, и управление получает оператор, стоящий за end; если при выполнении части try возникло исключение, управление получает соответствующий обработчик в секции except, а если таковой не найден - первый из операторов, стоящих
За словом else. В блоке finally операторы В секции finally. . .end получают управление всегда, независимо от того, возникло ли исключение в секции try.. .finally или нет. Если исключение возникло, все операторы в секции try.. .finally, стоящие за “виновником” исключения, пропускаются, и управление получает первый оператор секции finally... end. Если исключения не было, этот оператор получает управление после выполнения последнего оператора секции try.. .finally.
Обработчики исключений в блоке except имеют такой синтаксис:
on <класс исключения> do <оператор>;
Здесь on, do - зарезервированные слова; <класс исключения> -класс обработки исключения; <оператор> - любой оператор Object Pascal, кроме оператора передачи управления goto на метку вне блока except.
Обратите внимание: имя класса служит своеобразным ключом выбора, а собственно обработка осуществляется оператором, стоящим за do (этот оператор может быть составным, так что обработка исключения может занимать произвольное количество операторов Object Pascal).
Поиск нужного обработчика осуществляется с начала списка вниз до тех пор, пока не встретится класс, способный обрабатывать исключение данного типа. Если подходящего класса не обнаружено, управление передается операторам, стоящим за словом else, а если таковых нет (часть else <операторы> может опускаться), выполняется умалчиваемая обработка исключения.
Если для программиста важен лишь сам факт возникновения исключения и несущественен тип связанной с ним ошибки, он может опустить в секции except.. .end обработчики вместе со словом else, оставив в ней лишь необходимый код реакции на любую ошибку:
try
except
ShowMessage('Ощибка!') ;
end;
Защищенные блоки могут вкладываться друг в друга на неограниченную глубину, т. к. везде, где в предыдущих описаниях использовались <операторы> ИЛИ <оператор>, могут использоваться любые операторы Object Pascal, в том числе и try... except или try...finally:
try
try finally
end;
except
on EMatchError do begin
try try end;
end;
end
end;
16.1.2. Класс Exception
Класс Exception является родительским классом для всех классов-исключений. Этот класс объявляется в модуле sysUtils следующим образом:
type
Exception = class(TObject)
private
FMessage: String;
FHelpContext: Integer;
public
constructor Create(const Msg: Strings);
constructor CreateFmt(const Msg: String;
const Args: array of const);
constructor CreateRes(Ident: Integers);
constructor CreateResFmt(Ident: Integer;
const Args: array of const) ;
constructor CreateHelp(const Msg: String; aHelpContext:
Integer) ;
constructor CreateFmtHelp(const Msg: String;
const Args: array of const; aHelpContext: Integers);
constructor CreateResHelp(Ident: Integer; aHelpContext:
Integer) ;
constructor CreateResFmtHelp(Ident: Integer;
const Args: array of const;
aHelpContext: Integers);
property HelpCoatext: Integer read FHelpContext write FHeipContext;
property Message: String read FMessage write FMessage;
end;
В классе определены целых 8 конструкторов для создания объекта. С их помощью можно прочитать текстовое сообщение из ресурса, отформатировать его, связать исключение с контекстной справочной службой. Свойство Message делает доступным частное поле FMessage, в котором содержится текстовое сообщение.
16.1.3. Стандартные классы исключений
В Delphi определены стандартные классы исключений, перечисленные в табл. 16.1. Именно эти имена, а также имена пользовательских классов (см. п. 16.1.5) могут использоваться в обработчиках исключении.
Таблица 16.1
Класс |
Родитель |
Обрабатываемое исключение |
EAbort |
Exception |
Реализует “тихую” (без какого-либо сообщения) обработку любого исключения |
EAbstractErrpr |
Exception |
Программа пытается вызвать абстрактный метод |
EAccessViolation |
Exception |
Программа пыталась обратиться к не принадлежащей ей области памяти или использует недействительный указатель |
EAppletException |
Exception |
Ошибка связана с созданием управляющих панелей в апплет-приложениях |
EArrayError |
Exception |
Возникает из-за различного рода ошибок при работе с массивами (неверный индекс, попытка вставить элемент в массив фиксированной длины или в отсортированный массив и т. п.) |
EAssertionFaild |
Exception |
Возбуждается отладочной процедурой Assert, когда тстируемое ею логическое выражение имеет значение False. |
EBitsError |
Exception |
Программа пыталась обратиться к свойству Bits объекта TBits с индексом меньше нуля или больше максимально допустимого значения |
EBrokerException |
Exception |
Объект-брокер не может найти сервер |
ECacheError |
Exception |
Ошибка в наборе данных для компонента Tde-cisionCube |
EClassNotFound |
EFilerError |
Для компонента, читаемого из потока данных, не найден соответствующий класс. Обычно возникает"в случае, когда в форму вставлен нестандартный компонент, а в библиотеке компонентов Delphi нет связанного с ним класса |
ECommonCalendar-Error |
Exception |
Возникает в объектах класса TCommonCalendar и его потомках, когда вводится неверная дата |
EComponentError |
Exception |
Возникает при различных манипуляциях программы с компонентом (программа не может зарегистрировать компонент, переименовать его или когда для его работы требуется интерфейс СОМ, который компонентом не поддерживается) |
EControlC |
Exception |
Возникает при нажатии Ctrl-C при работе приложения в режиме консолиЛ |
EConvertError |
Exception |
Ошибка преобразования в функциях StrToint или StrToFloat |
ECorbaDispatch |
Exception |
Возникает в программах, использующих технологию corba, при ошибках, связанных с несовпадением интерфейсов сервера и брокера данных |
ECorbaException |
Exception |
Возникает в программах, использующих технологию CORBA |
ECorbaUser-Exception |
ECorbaException |
Возникает как определяемая пользователем реакция на ошибки интерфейса |
EDatabaseError |
Exception |
Возникает, когда компонент обнаруживает ошибку в базе данных |
EDateTimeError |
Exception |
Возбуждается компонентом TDateTimePicker при попытке ввода неверной даты или времени |
EDBClient |
EDatabaseError |
Ошибка связана с неправильной работой Tcli-entDataSet |
EDBEditError |
Exception |
Возникает, когда компонент пытается использовать данные, несовместимые с заданной маской |
EDBEngineError |
EDatabaseError |
Связана с ошибками BDE |
EDimensionMar-Error |
Exception |
Возникает, когда используемый в кубе решений набор данных не имеет агрегатных полей |
EDimIndexError |
Exception |
Связана с нарушением размерности массива данных для куба решений |
EDivByZero |
EIntError |
Ошибка целочисленного деления на ноль |
EDSWriter |
Exception |
Ошибка при подготовке провайдером пакета данных для набора данных |
EExternal-Exception |
EStream-Error |
Возникла ошибка, код которой не является предопределенным в Delphi |
EFCreateError |
EStream-Error |
Ошибка при создании файла. Например, попытка создать файл на устройстве, предназначенном только для чтения, или в несуществующем каталоге |
EFilerError |
EStream-Error |
Программа пытается повторно зарегистрировать в потоке один и тот же класс |
EFOpenError |
EStream-Error |
Ошибка открытия потока данных. Например, попытка открыть несуществующий файл |
EHeapException |
Exception |
Ошибка связана с неправильными операциями над динамической памятью |
ElBClientError |
ElBError |
Ошибка связана с функционированием IBX-клиента |
ElBError |
EDatabaseError |
Общая ошибка технологии IBX |
ElBInterbase-Error |
ElBError |
Ошибка связана с функционированием сервера в технологии IBX |
EInOutError |
Exception |
Любая ошибка в файловых операциях. Поле ErrorCode объекта этого класса содержит код ошибки |
EInterpreterError |
Exception |
Возникает, когда компонент класса TDataBlockinterpeter не может интерпретировать данные блока данных |
EIntError |
Exception |
Любая ошибка в целочисленных вычислениях |
EIntfCastError |
Exception |
Попытка недопустимого приведения типов в OLE-объектах |
EIntOverflow |
EIntError |
Ошибка целочисленного переполнения: программа пытается присвоить целочисленной переменной значение, выходящее из 32-двоичных разрядов |
EInva1i dArgument |
EMatchError |
Возбуждается математическими функциями при выходе аргумента из допустимого диапазона |
EInvalidCast |
Exception |
Программа пытается осуществить недопустимое преобразование типов с помощью оператора as |
EInvalidGraphic |
Exception |
Программа пытается загрузить в контейнер изображение из файла, который имеет недопустимый формат (допустимыми форматами являются растр, метафайл, курсор, пиктограмма) |
EInvalidGraphic-Operation |
Exception |
Программа пытается выполнить недопустимую графическую операцию |
EInvalidGrid-Operation |
Exception |
Программа пытается выполнить недопустимую операцию над таблицей (например, обратиться к несуществующему столбцу или РЯДУ) |
EInvalidImage |
EFilerError |
Программа пытается прочитать ресурс изображения из файла, в котором этого ресурса нет |
EInvalidOp |
EMatchError |
Ошибка в операциях с плавающей точкой (недопустимая инструкция, переполнение стека сопроцессора и т. п.) |
EInvalidOpera-tion |
Exception |
Не имеющий окна компонент пытается выполнить операцию, требующую дескриптора окна |
EInvalidPointer |
EHeap-Exception |
Попытка использовать недействительный указатель |
EListError |
Exception |
Эта ошибка связана с неверными действиями программы по отношению к разного рода спискам. Например обращение к элементу списка с индексом меньше нуля или больше максимально допустимого |
ELowCapacity-Error |
Exception |
Ошибка возникает при попытке выделения памяти на устройстве, у которого нет нужной свободной памяти. |
EMatchError |
Exception |
Любая ошибка при выполнении вычислений с плавающей точкой. |
EMenuError |
Exception |
Ошибка при работе программы с меню. Например, при добавлении элемента с идентификатором, который уже определен в меню |
EMCIDiviceError |
Exception |
Ошибка возникла в медиаплейере |
EMethodNotFound |
EFilerError |
Программа прочитала из потока данных объект, но не может найти связанный с классом объекта метод |
EMonthCalError |
ECommon-Calendar-Error |
Возбуждается компонентом класса TMonthcal-endar при попытке ввода неправильной даты |
EOleCtrlError |
Exception |
Программа не может установить связь с элементом ActiveX |
EOleError |
Exception |
Низкоуровневая ошибка в технологии OLE |
EOleException |
EOleSysError |
Программа использует неверный OLE-интерфейс |
EOleRegistration Error |
EOleError |
Ошибка регистрации OLE-объекта в реестре Windows |
EOleSysError |
EOleError |
Возникает при неправильном выполнении команды OLE автоматизации |
EOutlineError |
Exception |
Возникает при ошибке доступа к компоненту класса ToutLine |
EOutOfMemory |
EHeap-Exception |
Эта ошибка возникает, когда программа запрашивает слишком большой для данной конфигурации Windows объем памяти |
EOutOfResource |
EOutOfMemory |
Программа требует от Windows дескриптор окна, но Windows исчерпала лимит дескрипторов |
EOverflow |
EMatchError |
Результат операций с плавающей точкой слишком велик, чтобы уместиться в регистрах сопроцессора |
EPackageError |
Exception |
Возникает при ошибке доступа к пакету |
EParserError |
Exception |
Ошибка преобразования текста в двоичные данные при чтении из потока |
EPrinter |
Exception |
Windows сообщила программе об ошибке принтера |
EPrivilege |
Exception |
Программа пытается выполнить привилегированную операцию. Привилегированные операции могут выполняться только ядром Windows |
EPropertyConvert Error |
Exception |
Ошибка при чтении или записи значения свойства |
EPropertyError |
Exception |
Ошибка доступа к свойству при чтении или записи |
EPropReadOnly |
Exception |
Программа пытается присвоить значение свойству, из которого можно только читать (при использовании технологии OLE) |
EPropWriteOnly |
Exception |
Программа пытается прочитать свойство, предназначенное только для записи |
ERangeError |
EIntError |
Целочисленный результат превышает емкость целого типа данных |
EReadError |
EFilerError |
Программа не может прочитать из потока данных нужного количества байт |
EReconcileError |
EData-baseError |
Ошибка обновления данных в TclientDataset |
ERegistry-Exception |
Exception |
Ошибка, связанная с операцией над реестром Windows |
EResNotFound |
Exception |
Программа не может найти указанный ресурс в файле ресурсов |
ESocketConnec-tionError |
Exception |
Ошибка связана с работой с сокетами Windows |
ESocketError |
Exception |
Ошибка связана с работой с сокетами Windows |
EStackOverflow |
Exception |
Исчерпан объем выделенного программе стека |
EStreamError |
Exception |
Любая ошибка при работе с потоком данных |
EStringListError |
Exception |
Программа ссылается на строку, индекс которой выходит из диапазона возможных значений для списка строк |
EThread |
Exception |
Ситуация борьбы за общий ресурс в программе с несколькими потоками команд |
ETreeViewError |
Exception |
Указан неверный индекс при обращении к TtreeView |
EUnderflow |
EMatchError |
Результат операций с плавающей точкой слишком мал, чтобы уместиться в регистрах сопроцессора (исчезновение порядка) |
EUnsupportedTypeE rror |
Exception |
Выбран недопустимый тип поля в качестве измерения в кубе решений |
EUpdateError |
Exception |
Ошибка обновления провайдерского набора данных |
EVariantError |
Exception |
Ошибка при работе с типом Variant: недопустимое приведение типов; недопустимая операция; обращение -к скалярной переменной как к варианту-массиву; индекс варианта-массива выходит из допустимых значений |
EWin32Error |
Exception |
Ошибочное обращение к API-функции Windows. Свойство Message содержит номер ошибки и связанное с ней сообщение |
EWriteError |
EFilerError |
Ошибка записи в поток данных |
EZeroDivide |
EMatchError |
Вещественное деление на ноль |
Важно помнить, что ищется самый первый из, возможно, нескольких обработчиков, класс которого способен обрабатывать данное исключение. Если, например, в списке первым стоит EAbort, который может обработать любое исключение, ни один из стоящих за ним обработчиков никогда не получит управления. Точно так же, если указан обработчик для класса EintError, за ним бесполезно размещать Обработчики EDivByZero, ERangeError или EIntOverflow:
try
except
// He имеет смысла делать так:
on EintError do .....;
on ERangeError do .....;
on EDivByZero do .....;
// Надо так:
on ERangeError do .....;
on EDivByZero do .....;
on EintError do .....;
end;
При возникновении исключительной ситуации объекты классов-обработчиков создаются и уничтожаются автоматически. Если программист пожелает использовать поля или методы класса-обработчика явно, он должен поименовать автоматически создаваемый объект. Для этого перед именем класса ставится идентификатор и двоеточие:
on EObject: EClassName do .....;
Для стандартных классов такой прием фактически позволяет использовать единственное строковое свойство Message со стандартным сообщением об ошибке, которое получают все наследники класса Exception. Исключение составляет класс EInOutError, в котором для программиста может представлять интерес целочисленное свойство ErrorCode с кодом ошибки ввода/вывода.
Например:
Reset(F) ;
while not EOF(F) do begin
end;
CloseFile(F) ;
except
on E: EInOutError do
ShowMessage('При выполнении файловой операции возникла'+ ' ошибка №'+ IntToStr(E.ErrorCode));
end;
16.1.4. Вызов исключения
В некоторых ситуациях программисту бывает необходимо инициировать собственное исключение. Для этого он использует зарезервированное слово raise (возбудить). Если это слово встретилось в секции try.. .exception или try.. .finally, немедленно начинают свою работу секции соответственно except... end и finally... end. Если оно встретилось в except.. .end или finally.. .end, считается, что данный защищенный блок на текущем уровне вложенности (блоки могут быть вложенными) завершил свою работу и управление передается вышестоящему уровню.
Слово raise возбуждает исключение самого общего класса Exception. Если программист желает возбудить исключение конкретного типа (не важно - стандартного или собственного), он должен явно указать класс создаваемого в этот момент объекта путем вызова его конструктора. Например, следующий оператор возбудит ошибку ввода/вывода:
raise EInOutError.Create('Ощибка!') ;
Такой прем - единственная возможность возбудить нестандартное исключение, обрабатываемое пользовательским классом.
16.1.5. Создание собственного класса
Программист может создать собственный класс обработки исключений, объявив его потомком Exception или любого другого стандартного класса (этим другим чаще всего бывает класс EAbort). Объявление нестандартного класса имеет смысл только тогда, когда вам необходимо научить программу распознавать некорректные наборы данных и соответствующим образом на них реагировать.
Пусть, например, в программе используется цикл ввода целочисленных значений из текстового файла, их проверки и преобразования. Проверка заключается в простом контроле неотрицательности очередного числа после ввода и его положительности после преобразования. Перед проверкой необходимо получить строку из файла (здесь может возникнуть ошибка EinOutError) и преобразовать ее в целую величину (здесь возможна ошибка EConvertError); после проверки осуществляется обработка величины, в процессе которой может возникнуть ошибка EIntError.
Создадим новый класс EIntCheckError и будем возбуждать исключение этого класса при обнаружении ошибки в данных:
type
EIntCheckError = class(EAbort)
end;
var
F: TextFile;
S: String;
k: Integer;
begin
try
// Готовимся к работе: открываем файл AssignFile(F, FileName);
Reset(F); // Здесь возможна ошибка EinOutError // Цикл ввода-контроля-преобразования while not EOF(F) do begin
// Вводим символы очередного числа
ReadLn(F,S);// Здесь возможна ошибка EinOutError
// Преобразуем символы в число
k := StrToInt(S); // Здесь возможна ошибка EConvertError
// Проверяем число
if k < 0 then
raise EIntCheckError.Create("Отрицательное число');
// Преобразуем число
..... // Здесь возможна ошибка EIntError
// Вновь проверяем число
if k <= 0 then
raise EIntCheckError.Create('He положительное число');
end;
except
on E: EIntCheckError do
ShowMessage(E.Message) ;
on EInOutError do
ShowMessage('Некорректная файловая операция');
on EConvertError do
ShowMessage('Ошибка в записи числа');
on EIntError do
ShowMessage('Ошибка преобразования');
end;
end;
В этом примере создается класс EIntCheckError, который ничем, кроме названия, не отличается от своего родителя EAbort. В реальной программе потомок обычно расширяет набор полей (свойств) своего родителя или перекрывает его методы; приведенный пример лишь иллюстрирует, что делать это необязательно. При неудачной проверке операторами
raise EIntCheckError.Create('Отрицательное число') ;
и
raise EIntCheckError.Create('Ошибка преобразования');
возбуждается исключение нового класса. При этом с помощью унаследованного конструктора create создается новый безымянный объект, а строковый параметр обращения к конструктору запоминается в поле FMessage и становится доступен с помощью свойства Message объекта. Обработчик исключения EIntCheckError именует объект идентификатором e и с помощью стандартной процедуры ShowMessage показывает его в небольшом окне на экране.
Пример наглядно показывает выгоды использования исключений. В принципе весь этот фрагмент можно было бы написать с многочисленными проверками if... then, но в этом случае логика программы стала бы запутанной, а сама программа - сложной в отладке.
16.2. КЛАСС TLIST - СПИСКИ
Класс TList позволяет создать набор из произвольного количества элементов и организовать индексный способ доступа к ним, как это делается при работе с массивом. Списки отличаются от массивов двумя важными особенностями. Во-первых, их размер может динамически меняться в ходе работы программы, фактически ограничиваясь лишь доступной памятью. Во-вторых, в списках могут храниться элементы разных типов.
Технически списки представляют собой массивы нетипизированных указателей на размещенные в динамической памяти элементы. Эти массивы размещаются в куче - отсюда возможность динамического изменения размеров списков; с другой стороны, входящие в списки нетипизированные указатели позволяют ссылаться на произвольные элементы.
Свойства класса:
property List: pPointerList; |
Возвращает указатель на массив элементов списка |
property Capacity: Integers; |
Содержит количество элементов массива указателей списка. Всегда больше Count. Если при добавлении очередного элемента Count стало равно Capacity, происходит автоматическое расширение списка на 16 элементов |
property Count: Integer; |
Количество элементов списка. Это свойство изменяется при добавлении или удалении элемента |
property Items(Index: Integer): Pointers; |
Возвращает указатель на элемент списка по его индексу. Самый первый элемент списка имеет индекс 0 |
Тип pPointerList определен следующим образом:
type
pPointerList = PPointerList;
TPointerList = array [0..MaxListSize] of Pointer;
Константа MaxListSize для Delphi 1 ограничена значением 16379 элементов. Для старших версий Delphi она ограничивается доступной памятью.
Следует учесть, что свойство count определяет количество помещенных в список элементов, в то время как capacity - текущую емкость списка. Если при добавлении очередного элемента обнаруживается, что емкость списка исчерпана, происходит наращивание емкости на фиксированную величину (для count < 5 - на 4 элемента, для 4 < count < 8 - на 8, для Count > 7 - на 16). При этом сначала резервируется память для размещения расширенного массива указателей, затем в нее копируется содержимое старого массива, после чего старый массив указателей уничтожается (занимаемая им память возвращается Windows).
Если вы заранее знаете, сколько элементов необходимо поместить :в список, установите в начале работы нужное значение в свойство Саpacity - это снизит непроизводительные затраты времени на расширение списка.
Методы класса:
function Add(Item: Pointer): Integer; procedure Clear; |
Добавляет элемент item в конец ci; вращает его индекс Очищает список, удаляя из него вес Не освобождает память, связанную удаленным элементом. Устанавлив: ства Count и Capacity значение 0 |
procedure Delete(Index:Integer); |
Удаляет из списка элемент с индекс все элементы, расположенные за удаляемым, смещаются на одну позицию вверх |
class procedure Er ror(const Msg: Stringy; Data: Integer); virtual; |
Возбуждает исключение ElistErr метрами Msg и Data |
procedure Ex change (Indexl, Index2:Integer) ; |
Меняет местами элементы с индексами index1 иI ndex2 |
function Expand: TList; function Extract(Item: Pointer): Pointer; |
Расширяет массив, увеличивая Capacity Удаляет из списка элемент Item |
function First: Pointer; |
Возвращает указатель на самый первый элемент списка |
function IndexOf(Item:Pointer): Integer; |
Отыскивает в списке элемент Item и возвращает его индекс |
procedure Insert(Index: Integer; Item: Pointer) ;
|
Вставляет элемент Item в позицию Index списка: новый элемент получает индекс Index, все элементы с индексами Index и больше увеличивают свой индекс на 1. При необходимости расширяет список |
function Last: Pointer;
|
Возвращает указатель на последний элемент списка |
procedure Move(Curlndex, Newlndex: Integers; |
Перемещает элемент в списке с позиции CurIndex в позицию Newlndex. Все элементы старого списка с индексами от Curlndex-1 до Newlndex уменьшают свой индекс на 1 |
procedure Pack;
|
Упаковывает список: удаляет пустые элементы в конце массива индексов |
function Remove(Item: Pointer): Integer; |
Отыскивает в списке элемент Item и удаляет его |
procedure Sort(Compare: rListSortCompare); |
Сортирует коллекцию с помощью функции Compare |
Методы Add и insert получают указатель на вставляемый элемент. Чтобы воспользоваться ими, программист должен сам разместить в куче данные и получить соответствующий указатель. Точно так же методы Delete, Remove и Сlear не уничтожают распределенные в памяти данные, которые программист должен, если это необходимо, уничтожить сам.
Например:
var
List: TList;
Item: Pointer;
Value: AnyType;
begin
List := TList.Create; // Создаем список
Item := New(Value); // Размещаем в куче данные
List.Add(Item); // Добавляем элемент к списку .....
List.Remove(Item); // Удаляем элемент из списка
Dispose(Item); // Удаляем его из кучи
List.Free; // Удаляем ненужный список
end;
Метод sort сортирует список по критерию, устанавливаемому функцией compary. Тип TListSortCompare определен следующим образом:
TListSortCompare = function(Iteml, Item2: Pointer): Integer;
Таким образом, функция compare получает указатели на два элемента списка. Результат сравнения:
Критерий сравнения данных устанавливается программистом и реализуется в функции Compare.
В следующем примере в список List помещается 20 случайных вещественных чисел, равномерно распределенных в диапазоне 0...1.
Список сортируется по возрастанию чисел и отображается в компоненте mmOutput (многострочный редактор из учебной формы fmExample).
type
PDouble = ^Double;
Function Comp(Iteml, Item2:. Pointer): Integer;
// С помощью этой функции реализуется сортировка чисел
begin
if PDouble(Iteml)^ < PDouble(Item2)^ then
Result := -1 else
if PDouble(Iteml^ > PDouble (Item2) ^ then
Result := 1 else
Result := 0 end;
procedure TfmExample.bbRunClick(Sender: TObject);
// Обработчик нажатий кнопки bbRun выполняет основную работу
var
k: Integer;
List: TList;
pD: PDouble;
begin
List := TList.Create; // Создаем список
for k := 1 to 20 do // Наполняем его
begin
New(pD); // Резервируем память
pD^ := Random; // Помещаем в нее случайное число
List.Add(pD); // Добавляем к списку
end/List. Sort (Comp) ; // Сортируем список по возрастанию mmOutput.Lines.Clear;
{ Очищаем редактор mmOutput. В следующем цикле наполняем mmOutput и уничтожаем элементы List }
for k := 0 to List.Count-1 do
begin
pD := List[k]; // Очередное число из списка
mmOutput. Lines .Add (FloatToStr (pD^ );
{Помещаем в mmOutput}
Dispose(pD) // Уничтожаем число
end;
List.Free; // Уничтожаем список
end;
16.3. КЛАССЫ TSTRINGS И TSTRINGLIST -НАБОРЫ СТРОК И ОБЪЕКТОВ
16.3.1. TStrings
Абстрактный класс TStrings инкапсулирует поля и методы для работы с наборами строк. От него порождены многочисленные специализированные потомки, обслуживающие наборы строк в таких компонентах, как TComboBox, TListBox, TRichEdit и др. Эти классы
(TComboBoxStrings, TListBoxStrings, TRichEditStrings и др.) объявляются в разделах Implementation соответствующих модулей (Stdctris, Сomctris и др.) и поэтому скрыты от браузера Delphi и не включены в Help-службу. Единственным доступным наследником TStrings является TStringList - полнофункциональный класс общего назначения.
Замечательной особенностью TStrings и его потомков является то обстоятельство, что элементами наборов служат пары строка-объект, в которых строка - собственно строка символов, а объект -объект любого класса Delphi. Такая двойственность позволяет сохранять в TStrings объекты с текстовыми примечаниями, сортировать объекты, отыскивать нужный объект по его описанию и т. д. Кроме того, в качестве объекта может использоваться потомок от TStrings, что позволяет создавать многомерные наборы строк.
Свойства класса:
property Capacity: Integer; |
Текущая емкость набора строк |
property CommaText: String; |
Служит для установки или получения всего набора строк в виде единой строки с кавычками и запятыми (см. ниже пояснения) Текущее количество строк в наборе. |
property Count: Integer; |
Интерпретирует все строки списка в виде одной длинной строки |
property DelimitedText: String; |
Каждая строка окружается символами QuoteChar и отделяется от соседней символом Delimiter |
property Delimiter: Char; |
Символ для выделения строк в свойстве DelimitedText |
property Names[Index: Integer] : String; |
Для строки с индексом Index возвращает часть Name, если это строка вида Name=Value, в противном случае возвращает пустую строку |
property Objects[Index: Integer] : TObject; |
Открывает доступ к объекту, связанному со строкой с индексом Index |
property QuoteChar: Char; |
Символ для разделения строк в свойстве DelimitedText |
property Strings[Index: Integer] : String; |
Открывает доступ к строке с индексом Index |
property StringsAdapter: TStringsAdapter; |
Это свойство используется только при разработке компонентов, отвечающих стандарту Act iv |
property Text: String; |
Интерпретирует набор строк в виде одной длинной строки с разделителями eoln между отдельными строками набо |
property Values[const Name: String]: String; |
По части Name отыскивает в наборе и возвращает часть Value для строк вида Name=Valu |
Набор строк технически реализуется подобно TList - в виде массива указателей. Свойство Capacity показывает текущую длину этого массива, а свойство count - количество элементов, занятых в нем. Если при добавлении очередного элемента capacity окажется меньше count, происходит автоматическое расширение массива. При этом в динамической памяти резервируется место для размещения Capacity + 16 указателей, в новый массив переписывается содержимое старого массива, после чего старый массив уничтожается. Если вам известно количество элементов в создаваемом наборе строк, имеет смысл заранее нужным образом установить свойство capacity, чтобы сократить непроизводительные расходы на многократные расширения массива указателей.
Свойство commaText интерпретирует содержимое набора строк в виде одной длинной строки с элементами вида "первая строка", "вторая строка", "третья строка" и т. д. (каждая строка набора заключается в двойные кавычки и отделяется от соседней строки запятой; если в строке встречается символ “"”, он удваивается). Свойство Text интерпретирует содержимое набора в виде одной длинной строки с элементами, разделенными стандартным признаком eoln (#13#10).
Свойства Names И Values обрабатывают строки вида Name=Value.
Такие строки широко используются в различных файлах инициации, например, в файле win. ini. Методы класса:
function Add(const S: String) : Integer; function AddObject(const S:String; aObject: TObject):Integer; |
Добавляет строку в набор данных и возвращает ее индекс добавляет строку и объект в набор данных |
|
procedure AddStrings( Strings: TStrings); |
Добавляет к текущему набору новый набор строк |
|
procedure Append(const S:String) ; |
То же, что Add, но не возвращает индекс вставленной строки |
|
procedure Assign(Source: TPersistent) ;
|
Уничтожает прежний набор строк и загружает из Source новый набор. В случае не удачи возникает исключение EсоnvertError |
|
procedure BeginUpdate; |
Устанавливает флаг начала обновления. До вызова EndUpdate блокируется сортировка строк, что ускоряет процесс много кратного изменения данных |
procedure Clear; |
Очищает набор данных и освобождает связанную с ним память |
|
procedure Delete(Index: Integer) ;
|
Уничтожает элемент набора с индексом Index и освобождает связанную с ним память |
|
procedure EndUpdate; |
Сбрасывает флаг изменения и при необходимости сортирует строки |
|
function Equals(Strings:TStrings): Boolean; |
Сравнивает построчно текущий набор данных с набором Strings и возвращает True, если наборы идентичны |
|
procedure Exchange(Indexl, Index3: Integers;
|
Меняет местами строки с индексами Index1 и Index2. Если объект сортируется, вызывает исключение EstringListError |
|
function GetObject(Index:Integer): TObject; virtual; |
Возвращает объект, связанный со строкой Index |
|
function GetText: PChar;
|
Загружает строки из единого массива, в котором они отделяются друг от друга признаком EOLN |
|
function IndexOf(const S: String): Integer; |
Для строки S возвращает ее индекс или -1, если такой строки в наборе нет |
|
function IndexOfName(const Name: String): Integer; |
Возвращает индекс первой строки вида Name=Value, в которой часть Name совпадает с параметром обращения |
|
function IndexOfObject (aObject: TObject): Integer; |
Для объекта aObj ect возвращает индекс строки или -1, если такого объекта в наборе нет |
|
procedure Insert(Index: In teger; const S: Strings; |
Вставляет строку в набор и присваивает ей индекс Index |
|
procedure InsertObject (Index: Integer; const S: String; aObject: TObject) |
Вставляет строку и объект в набор и присваивает им индекс Index |
|
procedure LoadFromFile (const FileName: Strings; |
Загружает набор из файла
|
|
procedure LoadFromStream (Stream: TStream) ; |
Загружает набор из потока
|
|
procedure Move(Curlndex, Nwlndex: Integers; |
Перемещает строку из положения Curlndex в положение Newlndex |
|
procedure SaveToFile(const FileName: Strings; |
Сохраняет набор в файле
|
|
procedure SaveToStream (Stream: TStream) ; |
Сохраняет набор в потоке |
|
procedure SetText(Text: PChar); |
Выгружает строки в единый массив, в ко тором они отделяются друг от друга при знаком EOLN |
Методы Add, Append, Insert, Clear И Т. П. В классе TStrings - абстрактные. Связано это с тем, что класс инкапсулирует их и таким
образом делает доступными во всех потомках, но он при этом не накладывает никаких ограничений на то, как располагаются в памяти строки и объекты. Каждый потомок решает эту задачу наиболее удобным для него способом. Например, потомок TStringList располагает строки и объекты в общей динамической памяти, для чего перекрывает все абстрактные методы своего родителя. Замечу, что? если вы создадите экземпляр класса TStrings с помощью его конструктора Create, компилятор предупредит вас о том, что этот экземпляр содержит абстрактные методы, так что пользоваться им нужно лишь в исключительных случаях.
16.3.2. TStringList
TStringList представляет собой полнофункциональный класс общего назначения и является прямым потомкам TStrings. Помимо перекрытых абстрактных методов своего родителя класс включает в себя такие дополнительные методы и свойства:
property Duplicates: TDu-plicates; |
Свойство, позволяющее управлять возможностью размещения в наборе двух и более идентичных строк |
property Sorted: Boolean; |
Признак необходимости сортировки строк в алфавитном порядке |
property OnChange: TNotifyEvent;; |
Определяет реакцию на изменение набора строк. Возникает после последнего изменения |
property OnChanging: TNotifyEvent |
Определяет реакцию на изменение набора строк. Возникает до очередного изменения |
function Find(const S:String; var Index: Integer) : Boolean; |
Ищет в наборе строку S и в случае успеха в параметре index возвращает ее индекс |
При sorted = True строки набора автоматически сортируются в алфавитном порядке. При этом свойство Duplicates разрешает коллизию, связанную с добавлением в набор строки, идентичной одной из ранее вставленных. Если Duplicates = dulgnore, идентичная строка отвергается и программе ничего об этом не сообщается; если Duplicates = duError, возбуждается исключение EListError; значение Duplicates = duAccept разрешает вставлять в набор сколько угодно идентичных строк.
Следует заметить, что сортировка строк в Windows 32 осуществляется не совсем так, как это происходит в MS-DOS или Windows 3-х. Чтобы убедиться в этом, советую прогнать следующий вариант учебной программы (см. рис. 16.1). В ней обработчик события OnClick кнопки bbRun создает два списка строк - List1и List2. Список List1 первоначально способен сортировать строки (в его свойство sorted устанавливается значение True). Затем в цикле от 32 до 255 (О...31 - это коды служебных символов) происходит наполнение обоих списков: в List1 помещается строка, содержащая символ и его код, а в List2 - наоборот, сначала код, а затем сам символ. Поскольку символьное представление кода дополняется до трех символов (в двузначных числах слева добавляется ведущий ноль), строки в списке List1 окажутся отсортированными по символу, а в списке List2 - по коду символа. Затем оба списка для наглядности объединяются и помещаются в редактор mmOutput.
procedure TfmExample.bbRunClick (Sender: TObject);
var
k: Byte;
Listi, List2: TStringList;
S: String;
begin
// Создаем два списка
List1 := TStringList.Create;
Listi.Sorted := True;
List2 := TStringList.Create;
// Цикл наполнения списков монотонно возрастающими кодами
for k := 32 to 255 do
begin
S := IntToStr(k); // Код символа
if k<100 then
S := '0' + S;// Двузначное число дополняем ведущим нулем
// Формируем строку Listi из символа + табуляция + код символа Listi.Add(Char(k) + #9 + S) ;
// Формируем строку List2 из кода + табуляция + символ
List2.Add(S + #9 + Char(k));
end;
// Объединяем оба списка
Listi.Sorted := False; // Отключаем сортировку List1
for k := 0 to List1.Count-1 do
List1[k] := List1[k] + #9 + List2[k];
// Переносим результат в mmOutput mmOutput.Lines.Assign(List1);
// Уничтожаем List1 и List2 Listi.Free;
List2.Free;
end;
Следует прокомментировать два момента. Во-первых, с помощью единственного оператора
mmOutput.Lines.Assign(List1);
все строки List1 помещаются в свойство Lines редактора mmOutput. Это возможно из-за того, что mmOutput. Lines и Listi имеют общего родителя TStrings, который умеет копировать родственные наборы строк с помощью своего метода Assign. Во-вторых, перед объединением строк мы отключили свойство Sorted списка Listi. если этого не сделать, любое изменение строк в отсортированном списке привело бы к исключентю EStringListError.
Рис. 16.1. Окно прогона программы сравнения сортировки строк для Windows 32 и Windows З.х
Как видим, строки в 32-разрядных Windows сортируются не с учетом внутреннего кода символа, а с учетом “смысла”: в начале располагаются все знаки препинания и разного рода “мусор”, затем идут цифры, буквы латинского алфавита и символы кириллицы. Буквы упорядочены парами - сначала заглавная, за ней строчная - и не идут сплошным массивом. “Виновником” такой сортировки является API-функция AnsiCompareText, К который обращается метод TStringList. Quicksort. Если вам понадобится отсортировать так, как это принято в MS-DOS или Windows З.х, т. е. по коду символа, проделайте следующее.
Function AnsiCompareText(SI, S2: String): Integer;
begin
if S1 < S2 then Result := -1
else if SI == S2 then Result := 0
else Result := 1
end;
3. С помощью опции Project | Add To Project добавьте измененный модуль classes к вашему проекту и сделайте новый прогон программы. Теперь оба столбца будут идентичны.
16.4. ГРАФИЧЕСКИЙ ИНСТРУМЕНТАРИЙ
Богатство изобразительных возможностей Windows связано с так называемым дескриптором контекста графического устройства DC (Device Context) и тремя входящими в него инструментами - шрифтом, пером и кистью. В Delphi созданы специализированные классы-надстройки, существенно упрощающие использование графических инструментов Windows: для контекста - класс TCanvas, для шрифта - TFont, для пера - ТРеп и для кисти - TBrush.
Связанные с этими классами объекты автоматически создаются для всех видимых элементов и становятся доступны программе
через свойства Canvas, Font, Pen и Brush.
16.4.1. Класс TFont
С помощью класса TFont создается объект-шрифт для любого графического устройства (экрана, принтера, плоттера и т. п.).
Свойства класса:
property Color: TColor; |
Цвет шрифта |
property Charset: TFontCharSet; |
Набор символов. Для русскоязычных программ это свойство обычно имеет значение DEFAULTCHARSET или russian charset. Используйте значение OEMCHARSET для отображения текста MS-DOS (альтернативная кодировка) |
property FontAdapter: IChangeNotifier; |
Поставляет информацию о шрифте в компоненты ActveX |
property Handle:hFont; |
Дескриптор шрифта. Используется при непосредственном обращении к API-функциям Windows |
property Height: Integer; |
Высота шрифта в пикселях экрана |
property Name: TFontName; |
Имя шрифта. По умолчанию имеет значение MS Sans Serif |
property Pitch: TFontPitch;
|
Определяет способ расположения букв в тексте: значение fpFixed задает моноширинный текст, при котором каждая буква имеет одинаковую ширину; значение fpVariabel определяет ропорциональный текст, при котором ширина буквы зависит от ее начертания; fpDefault определяет ширину, принятую для текущего шрифта |
property PixelPerInch: Integer; |
Определяет количество пикселей экрана на один дюйм реальной длины. Это свойство не следует изменять, т. к. оно используется системой для обеспечения соответствия экранного шрифта шрифту принтера |
property Size: Integer; |
Высота шрифта в пунктах (1/72 дюйма). Изменение этого свойства автоматически изменяет свойство Height и наоборот. |
property Style: TFontStyles; |
Стиль шрифта. Может принимать значение как комбинация следующих признаков: fsBold (жирный), fsltalic (курсив), fsUnderline (подчеркнутый), fsStrikeOut (перечеркнутый) |
Для некоторых случаев может оказаться полезным метод
procedure Assign(Source: TPersistent);
с помощью которого значения свойств шрифтового объекта source присваиваются свойствам текущего шрифта. Метод не изменяет свойство pixeiperinch, поэтому его можно использовать для создания шрифта принтера по экранному шрифту и наоборот.
16.4.2. Класс ТРеп
С помощью класса треп создается объект-перо, служащий для вычерчивания линий. Свойства класса:
property Color: TColor; |
Цвет вычерчиваемых пером линий |
property Handle: Inte ger; |
Дескриптор пера. Используется при непосредственном обращении к API-функциям Windows |
property Mode: TPenMode; |
Определяет способ взаимодействия линий с фоном (см.ниже) |
property Style: TPenStyle; |
Определяет стиль линий (см. рис. 16.2). Учитывается только для толщины линий 1 пиксель. Для толстых линий стиль всегда ps Solid (сплошная) |
property Width: Integer; |
Толщина линий в пикселях экрана |
Свойство Mode может принимать одно из следующих значений: |
|
pmBlack |
Линии всегда черные. Свойства Color и Style игнорируются |
pmWhite |
Линии всегда белые. Свойства Color и Style игнорируются |
pmNop |
Цвет фона не меняется (линии не видны) |
pmNot |
Инверсия цвета фона. Свойства Color и Style игнорируются |
pmCopy |
Цвет линий определяется свойством Color пера |
pmNotCopy |
Инверсия цвета пера. Свойство Style игнорируется |
pmMergePenNot |
Комбинация цвета пера и инверсионного цвета фона |
pmMaskPenNot |
Комбинация общих цветов для пера и инверсионного цвета фона. Свойство Style игнорируется |
pmMergeNotPen |
Комбинация инверсионного цвета пера и фона |
pmMaskNotPen |
Комбинация общих цветов для инверсионного цвета пера и фона. Свойство Style игнорируется |
pmMerge |
Комбинация цветов пера и фона |
pmNotMerge |
Инверсия цветов пера и фона. Свойство Style игнорируется |
pmMask |
Общие цвета пера и фона |
pmNotMask |
Инверсия общих цветов пера и фона |
pmXor |
Объединение цветов пера и фона операцией XOR |
pinNotXor |
Инверсия объединения цветов пера и фона операцией XOR |
Стили линий показаны на рис. 16.2.
Рис. 16.2. Стили линий
16.4.3. Класс TBrush
Объекты класса TBrush (кисти) служат для заполнения внутреннего пространства замкнутых фигур.
Свойства класса:
property Bitmap: TBitmap; |
Содержит растровое изображение, которое будет использоваться кистью для заполнения. Если это свойство определено, свойства Color и Style игнорируются |
property Color: TColor; |
Цвет кисти |
property Handle: Integer; |
Дескриптор кисти. Используется при не посредственном обращении к API- функциям Windows |
property Style: TBrushStyle; |
Стиль кисти (см. рис. 16.3) |
16.4.4. Класс TCanvas
Этот класс создает “канву”, на которой можно рисовать чертежными инструментами - пером, кистью и шрифтом. Объекты класса ЕСаnvas автоматически создаются для всех видимых компонентов, которые должны уметь нарисовать себя. Они инкапсулируют объекты Font, pen, Brush, а также многочисленные методы, использующие эти объекты.
Свойства класса:
property Brush: TBrush; property ClipRect: TRect; |
Объект-кисть Определяет текущие размеры области, нуждающейся в прорисовке |
property CopyMode: TCopyMode; |
Устанавливает способ взаимодействия растрового изображения с цветом фона |
property Font: TFont; |
Объект-шрифт |
property Handle: Integer; |
Дескриптор канвы. Используется при непосредственном обращении к API-функциям Windows |
property LockCount: In tegers;
|
Счетчик блокировок канвы. Увеличивается на единицу при каждом обращении к методу Lock и уменьшается на единицу при обращении к Unlock |
property Pen: TPen; |
Объект-перо |
property PenPos:TPoint; |
Определяет текущее положение пера в пикселях относительно левого верхнего угла канвы |
property Pixels[X,Y:Integer]: TColor; |
Массив пикселей канвы
|
Свойство copyMode используется при копировании части одной канвы (источника) в другую (приемник) методом copyRect и может иметь одно из следующих значений:
cmBlackness |
Заполняет область рисования черным цветом |
cmDestInvert |
Заполняет область рисования инверсным цветом фона |
cmMergeCopy |
Объединяет изображение на канве и копируемое изображение операцией and |
cmMergePaint |
Объединяет изображение на канве и копируемое изображение операцией OR |
cmNotSrcCopy |
Копирует на канву инверсное изображение источника |
cmNotSrcErase |
Объединяет изображение на канве и копируемое изображение операцией OR и инвертирует полученное |
cmPatCopy |
Копирует образец источника |
cmPatInvert
|
Комбинирует образец источника с изображением на канве с помощью операции XOR |
cmPatPaint |
Комбинирует изображение источника с его образцом с помощью операции OR, затем полученное объединяется с изображением на канве также с помощью OR |
cmSrcAnd
|
Объединяет изображение источника и канвы с помощью операции AND |
cmSrcCopy |
Копирует изображение источника на канву |
cmSrcErase |
Инвертирует изображение на канве и объединяет результат с изображением источника операцией AND |
cmSrcInvert |
Объединяет изображение на канве и источник операцией XOR |
cmSrcPaint |
Объединяет изображение на канве и источник операцией OR |
cmWhitness |
Заполняет область рисования белым цветом |
С помощью свойства pixels все пиксели канвы представляются в виде двухмерного массива точек. Изменяя цвет пикселей, можно прорисовывать изображение по отдельным точкам.
Методы класса:
procedure Arc(X1, Y1, X2, Y2, ХЗ, Y3, Х4, Y4: Integer); |
Чертит дугу эллипса в охватывающем прямоугольнике (Xl,Yl)-(X2,Y2). Начало дуги лежит на пересечении эллипса и луча, проведенного из его центра в точку (ХЗ, Y3), а конец - на пересечении с лучом из центра в точку (Х4, Y4). Дуга чертится против часовой стрелки (см. рис. 16.4, а) |
procedure BrushCopy (const Dest: TRect; Bitmap: TBitmap; const Source: TRect; Color: TColor); |
Копирует часть изображения Source на участок канвы Dest. Color указывает цвет в Dest, который должен заменяться на цвет кисти канвы. Метод введен для совместимости с ранними версиями Delphi. Вместо него следует пользоваться классом Т Image List |
procedure Chord(XI, Yl, X2, Y2, X3, Y3, |
Чертит сегмент эллипса в охватывающем прямоуголь нике (XI, У1) - (X2, Y2). Начало дуги сегмента лежит на пересечении эллипса и луча, проведенного из его центра в точку (X3, Y3), а конец - на пересечении с лучом из центра в точку (X4, Y4). Дуга сегмента чертится против часовой стрелки, а начальная и конечная точки дуги соединяются прямой (см. рис. 16.4, б) |
procedure CopyRect (Dest: TRect; Canvas: TCanvas;Source: TRect) ; |
Копирует изображение Source канвы Canvas в участок Dest текущей канвы. При этом разнообразные специальные эффекты достигаются с помощью свойства CopyMode |
procedure Draw(X, Y:Integer; Graphic:TGraphic) ; |
Осуществляет прорисовку графического объекта Graphic так, чтобы левый верхний угол объекта расположился в точке (X, Y) |
procedure DrawFocusRect (const Rect:TRect) ; |
Прорисовывает прямоугольник с помощью операции XOR, поэтому повторная прорисовка уничтожает ранее вычерченный прямоугольник. Используется в основном для прорисовки нестандартных интерфейсных элементов при получении ими фокуса ввода и при потере его |
procedure Ellipse(XI, Yl, X2, Y2: Integers; |
Чертит эллипс в охватывающем прямоугольнике (XI, Yl) - (X2, Y2). Заполняет внутреннее пространство эллипса текущей кистью |
procedure FillRect(const Rect: TRect); |
Заполняет текущей кистью прямоугольную область Rect, включая ее левую и верхнюю границы, но не затрагивая правую и нижнюю границы |
procedure Flood- Fill(X, Y: Integer; Color: TColor; Fill Style: TFillStyle); |
Производит заливку канвы текущей кистью. Залив ка начинается с точки (X, Y) и распространяется вовсе стороны от нее. Если FillStyle=fsSurface, заливка распространяется на все соседние точки с цветом Color. Если FillStyle=fsBorder, наоборот, заливка прекращается на точках с этим цветом |
procedure FrameRect(const Rect: TRect); |
Очерчивает границы прямоугольника Rect текущей кистью толщиной в 1 пиксель без заполнения внутренней части прямоугольника |
procedure LineTo(X, Y: Integer); |
Чертит линию от текущего положения пера до точки (X,Y) |
procedure Lock;
|
Блокирует канву в многопоточных приложениях для предотвращения использования канвы в других по токах команд |
procedure MoveTo(X,Y: Integer); |
Перемещает перо в положение (X, Y) без вычерчивания линий |
procedure Pie(XI, Yl, X2, Y2, X3, Y3, X4, Y4: Longint);
|
Рисует сектор эллипса в охватывающем прямоугольнике (XI, Yl) - (X2, Y2). Начало дуги лежит на пересечении эллипса и луча, проведенного из его центра в точку (X3, Y3), а конец - на пересечении случом из центра в точку (X4, Y4). Дуга чертится против часовой стрелки. Начало и конец дуги соединяются прямыми с ее центром (см. рис. 16.4, в) |
procedure Polygon. (Points: array of TPoint) ;
|
Вычерчивает пером многоугольник по точкам, заданным в массиве Points. Конечная точка соединяется с начальной и многоугольник заполняется кистью. Без заполнения используйте - Polyline |
procedure Polyline (Points: array of TPoint); |
Вычерчивает пером ломаную прямую по точкам, заданным в массиве Points
|
procedure Rectan gle(XI, Yl, X2, Y2: Integer); |
Вычерчивает и заполняет прямоугольник (XI, Yl) -S(X2, Y2). Для вычерчивания без заполнения используйте FrameRect или Polyline |
procedure Refresh; |
Устанавливает в канве умалчиваемые шрифт и кисть |
procedure RoundRect(Xl, Yl, X2,Y2, X3, Y3: Inte ger) ; |
Вычерчивает и заполняет прямоугольник (XI,Yl)- (X2, Y2) со скругленными углами. Прямоугольник (XI, Yl) - (X3, Y3) определяет дугу эллипса для округления углов (см. рис. 16.4, г) |
procedure Stretch Draw (const Rect:TRect; Graphic: TGraphic ); |
Вычерчивает и при необходимости масштабирует графический объект Graphic так, чтобы он полностью занял прямоугольник Rect
|
function TextExtent (const Text:String): TSize; |
Возвращает ширину и высоту прямоугольника, охватывающего текстовую строку Text
|
function TextHeight (const Text: String): Integer; |
Возвращает высоту прямоугольника, охватывающего текстовую строку Text
|
procedure TextOut(X, Y: Integer; const Text: String) ; |
Выводит текстовую строку Text так, чтобы левый верхний угол прямоугольника, охватывающего текст, располагался в точке (X, Y) |
procedure TextRect(Rect: TRect; X, Y: Integer; const Text: String) ; |
Выводит текстовую строку Text так, чтобы левый верхний угол прямоугольника, охватывающего текст, располагался в точке (х, Y). Если при этом какая-либо часть надписи выходит из границ прямоугольника Rect, она отсекается и не будет видна |
function TextWidth (const Text:String): Integer; |
Возвращает ширину прямоугольника, охватывающего текстовую строку Text
|
function TryLock: Boolean; |
Пытается заблокировать канву. Если она не заблокирована другим потоком команд, - True, в противном случае ничего не делает и возвращает False |
procedure Unlock; |
Уменьшает на 1 счетчик блокировок канвы |
16.4.4.1. Дополнительные возможности API-функций
Замечу, что все богатство изобразительных возможностей Windows далеко не исчерпывается набором свойств и методов класса TCanvas: этот класс инкапсулирует лишь наиболее популярные приемы работы с чертежными инструментами. В этом разделе перечисляются некоторые функции Windows, которые не инкапсулирует класс TCanvas и которые способны значительно разнообразить текстовый вывод (именно он наиболее обеднен узкими рамками TCanvas).
Некоторые текстовые функции API
type TLogFont = record If Height: Integer; IfWidth: Integer; IfEs- capment: Integer; IfOri- entation: Integer; IfWeight: Integer; If Italic: Byte; IfUnder- line: Byte; IfStrikeOut: Byte; IfCharSet: Byte; IfOutPrecision: Byte; IfClipPrecision: Byte; IfQuality: Byte; IfPitchAndFamily: Byte; 1fFaceName: PChar ; end; function CreateFont(Font: TLogFont): hFont; |
Создает новый шрифт на основе данных в параметре Font. Назначение полей структуры TLogFont см. после таблицы
|
function DrawText(DC:hDC; pText: PChar; varRect:'TRect; Format:UINT): Integer; |
В прямоугольнике Rect выводит многострочный текст, на который указывает pText. Параметр Format используется для форматирования (см.ниже) |
function ExtTextOut(DC: hDC; X, Y: Integer; Op tions: Integer; Rect: TRect; pText: PChar; Count: Integer; PX: PInteger): Bool;
|
Выводит текст с нестандартными меж сим вольными расстояниями: X, Y - верхняя левая точка текста; Options - параметр, управляющий выводом (см. ниже); Rect - ограничивающий прямоугольник; pText - указатель на строку вывода; Count - количество выводимых символов; px - указатель на массивцелочисленных значений, определяющих межсимвольные расстояния: 1-й параметр - расстояние от 1-го до 2-го символа; 2-й параметр- расстояние от 2-го до 3-го символа и т. д.; если какой-то параметр равен 0, используется умалчиваемое межсимвольное расстояние |
function GetBkColor(DC:hDC): TColor; |
Возвращает цвет фона
|
function GetBkMode(DC:hDC) : Integer;
|
Возвращает режим прорисовки фона: Opaque - фон прорисовывается заново при выводе текста; Transparent - фон не прорисовывается |
function GetTextAlign(DC: hDC) : Integer; |
Возвращает выравнивание текста
|
function GetTextCharacterExtra(DC: hDC): Integer; |
Возвращает межсимвольное расстояние |
function SetBkColor(DC:hDC; Color: TColor): TColor; |
Устанавливает новый цвет фона и возвращает старый, если обращение успешно |
function SetBkMode(DC:hDC; Mode: Integer): Integer; |
Устанавливает новый режим прорисовки фона и возвращает старый, если операция успешна |
function SetTextAlign(DC: hDC; Flags: Integer): Integer; |
Устанавливает новое выравнивание текста и возвращает старое, если вызов успешен |
function SetTextCharacterExtra(DC: hDC; CharExtra: Integer): Integer; |
Устанавливает новое межсимвольное расстояние и возвращает старое, если вызов успешен |
Отдельные поля структуры TLogFont для функции CreateFontIndirect имеют следующий смысл:
if Height - высота шрифта в пунктах (1 пункт = 1/72 дюйма); если больше 0, определяет высоту “знакоместа” (с учетом выступающих над заглавным символом элементов в буквах Е, И), если меньше нуля - высоту “чистого” символа, если 0 - высоту выбирает Windows;
if width - средняя ширина символа; если 0, ширину устанавливает Windows;
ifEscapment - угол наклона базовой линии текста в десятых долях градуса относительно горизонтального направления; положительные значения - поворот по часовой стрелке; в Windows 95/98 совпадает СIfOrientation;
iforientation - угол наклона символов по отношению к базовой линии; в Windows NT для шрифтов True Type может отличаться от ifEscapment; для этого следует установить режим устройства отображения равным gm_Advanced (по умолчанию устанавливается gm_Compatible);
IfWeight - плотность шрифта (fm_DontCare=0 - плотность выбирает Windows; fm_Thin=100 - очень тонкий шрифт;
fm_ExtraLight=200 - очень светлый; fm_Light=300 - светлый;
fm_Normal=400 - нормальный; fm_Medium=500 - утолщенный;
fm_SemiBold=600 - полужирный; fm_Bcld=700 - жирный;
fm_ExtraBold=800 - усиленный; fm_Heavy=900 - тяжелый);
ifitalic, ifunderiine, ifStrikeOut - ненулевое значение означает соответственно наклонный, перечеркнутый и подчеркнутый шрифт;
IfCharSet - Набор символов (ANSI_CharSet=0, Default_CharSet=l;
Symbol_CharSet=2;ShiftJis_CharSet=128;OEM_CharSet=255);
ifoutprecision - точность представления шрифта; рекомендуется out__TT_prec (выбирает True Type и векторные шрифты, если есть несколько разновидностей одноименных шрифтов) или out_TT_oniy_prec (только True Type);
ifciipprecision - определяет точность отсечения надписи границами области прорисовки (Clip_Character_Precis, Clip_Embedded, Clip_Mask, Clip_TT_Always, Clip_Default_Precis - рекомендуется, Clip_LH_Angles, Clip_Stroke_Precis);
IfQuality - Определяет качество прорисовки (Default_Quality, Draft_Quality,Proof_Quality);
ifpitchAndFamily - в четырех младших разрядах указывается тип шрифта, в четырех старших ~ его семейство;
IfFaceName - имя гарнитуры шрифта.
Вот как реализован этот пример.
procedure TForm1.FormPaint(Sender:TObject) ;
var
X: Integer;
LF: TLogFont;
Fnt: HFont;
const
Text = 'Лучшая в мире система программирования';
begin
// Определяем параметры нового шрифта
FillChar(LF, SizeOf(LF), 0) ;
with LF do
begin
If Height := 20;
If Weight := fw_Normal;
If Underline := 1;
If Escapement := 450;
StrPCopy(lfFaceName, 'Courier New Cyr');
end;
with Forml.Canvas do
begin
// Создаем шрифт
Fnt := CreateFontIndirect(LF) ;
// Присваиваем его дескриптор шрифту канвы
Font.Handle := Fnt;
// Выводим текст под углом +45 градусов
Text0ut(0, 300, Text);
X := TextWidth(Text) ;
DeleteObject(Fnt); // Удаляем ненужный шрифт
// Изменяем параметры шрифта
with LF do
begin
If Height := 90;
IfEscapement := -900;
IfWeight := fw_Heavy;
StrPCopy(LF.lfFaceName, 'Arial Cyr');
end;
Fnt := CreateFontIndirect(LF); // Создаем новый шрифт
Font.Handle := Fnt;
Font.Color := clRed;
// Выводим с наклоном -90 градусов
TextOut(X-10, 10, 'Delphi 5');
DeleteObject(Fnt); // Удаляем ненужный шрифт
end;
end;
Параметр Format функции DrawText может содержать один или несколько следующих флагов.
Возможные значения параметра Format функции DrawText
dt Bottom |
Текст прижимается к нижней части области Rect |
dtCalcRect |
Разрешает динамически изменять размеры области Rect |
dtCenter |
Текст центрируется по горизонтали |
dtEditControl
|
Функция дублирует свойства отображения многострочного тестового редактора. В частности, таким же способом вычисляется средняя ширина символа и не показывается частично видимая последняя строка |
dtExpandTabs |
Символы табуляции заменяются пробелами |
dt ExternalLeading |
В высоту строки включается высота межстрочного интервала |
dtLeft |
Текст прижимается к левой части области Rect |
dtNoClip |
Текст не отсекается границами Rect |
dtNoPrefix |
Символы & не заменяются подчеркиванием |
dtRight |
Текст прижимается к правой части области Rect |
dt SingleLine |
Весь текст выводится единственной строкой, символы EOLN игнорируются |
dt TabsStop |
Символы табуляции не заменяются пробелами |
dtTop |
Текст прижимается к верхней части области R'ect |
dtVCenter |
Текст центрируется по вертикали |
dtWordBreak |
Разрешает переход на новую строку при достижении пра вой границы Rect; разрыв строки - на границе слова; символы EOLN также переводят вывод на следующую строку |
Если установлен флаг dt_caicRect, функция изменяет высоту и ширину прямоугольника так, чтобы вывести весь текст, но сам текст не выводится. Если в тексте несколько строк, ширина вывода не меняется. Функция возвращает истинную высоту прямоугольника вывода.
Параметр options функции ExtTextOut может быть комбинацией следующих значений:
eto_Сlipped - текст будет отсекаться границами Rect;
eto_Gliph_index - блокирует обработку языковым драйвером;
eto_opaque - фон перерисовывается заново;
eto_RTLReading - вывод для чтения справа налево. При выводе текста стандартными методами rcanvas всегда заново прорисовывается фон символов (цвет фона возвращает функция GetBkColor). Если цвет фона символов отличается от фона канвы, вывод сопровождается неприятными побочными эффектами. Если в предыдущем примере для формы оставить стандартный цвет ciFaceBtn, окно вывода будет таким, как на рис. 16.6. Конечно, с помощью функции setBkcoior можно установить цвет формы совпадающим с цветом канвы, однако это не всегда возможно. Ясно, что установить переменный цвет функцией SetBkcoior невозможно. Более того, заглавные надписи программ Setup.exe также традиционно выводятся утолщенным наклонным шрифтом Times New Roman белыми буквами с черной тенью. Реализовать такой эффект достаточно просто: нужно вообще отказаться от прорисовки фона, установив с помощью функции SetBkMode режим Transparent, и вывести надпись дважды: первый раз черным цветом, а второй -белым, сместив вторую надпись немного влево и вверх относительно первой. Следующий листинг иллюстрирует сказанное.
procedure TFormI.FormPaint(Sender: TObject);
var
Y: Integer;
Blue: Byte;
const
Text = 'Фон для программы Setup.exe';
begin
with Forml.Canvas do
begin
for Y := 0 to Forml.Height-1 do
begin
// Уменьшаем интенсивность цвета с ростом ординаты Y
Blue := Round($FF*(Forml.Height-Y)/Forml.Height);
Pen.Color := RGB(0, 0, Blue); // Формируем цвет
MoveTo(0, Y); // Чертим линию
LineTo(Forml.Width-1, Y) ;
end; //for Y := 0 to Forml.Height-1 do Font.Size := 32;
Font.Style := [fsBold, fsltalic, fsUnderline];
Font.Name := 'Times New Roman";
// Это обращение накладывает текст на фон SetBkMode(Handle, Transparent);
// Сначала выводим тень надписи
Font.Color := clBlack;
Text0ut(40, 30, Text);
// Теперь саму надпись Font.Color := clWhite;
Text0ut(36, 26, Text)
end; //with Forml.Canvas do end;
Замечу, что любая заливка фона, в том числе его прорисовка, реализуется с помощью кисти. Поэтому отказаться от прорисовки фона текста можно, если установить стиль кисти bsciear: вместо
SetBkMode(Handle, Transparent);
можно использовать
Brush.Style := bsClear;
16.4.4.2. Области
К сожалению, в класс TCanvas не включена еще одна изобразительная возможность Windows - области (Regions). Области - такие же графические объекты, как перо, кисть, шрифт. Они образуются с помощью комбинации простейших геометрических фигур - прямоугольников, многоугольников, эллипсов. Замечательной особенностью областей является возможность создания с их помощью непрямоугольных кнопок, цветовых областей, окон. А вот как оно было создано:
uses
Forms,
Unit1 in 'Unitl.pas' {Formi}, Windows; // Этот модуль экспортирует функции API
{$R *.RES} var
Rgn: Cardinal;
begin
// Сначала создаем обычное окно:
Application.CreateForm(Tform1, Form1);
with Formi.Canvas, Formi do
begin
// Теперь создаем в нем эллиптическую область
Rgn := CreateEllipticRgn(0, 0, Width, Height);
// и показываем ее вместо окна
SetWindowRgn(Handle, Rgn, True);
end;
Application.Run;
end.
Ниже перечислены основные функции для работы с областями.
Работа с областями
function CombineRgn(DestRgn, Rgnl, Rgn2: Cardinal; Com-bineMode: Ineger): Integer; |
Объединяет две области в одну: DestRgn - дескриптор результирующей области; Rgnl, Rgn2 -дескрипторы объединяемых областей; CombineMode - параметр, указывающий способ объединения; этот параметр, а также возвращаемое значение описаны ниже |
function CreateEllipticRgn(XI, Yl, X2, Y2: Integer) : Cardinal; |
Создает эллиптическую область |
function CreatePoly-gonRgn(var Points; Count, PolyFillMode: Integer): Cardinal; |
Создает область в виде многоугольника: Points - массив координат всех вершин многоугольника; Count - количество вершин; PolyFillMode -режим заполнения многоугольника (см. ниже) |
function CreateRectRgn(XI, Yl, X2, Y2: Integer): Cardi nal; |
Создает прямоугольную область
|
function CreateRoundRectRgn(Xl, Yl, X2, Y2, X3, Y3: Integer): Cardinal; |
Создает область со скругленными углами; параметры обращения иллюстрирует |
function EqualRgn(Rgnl,Rgn2: Cardibal): Bool; |
Проверяет эквивалентность двух областей |
function FillRgn(DC, Rgn,Brush: Cardinal): Bool; |
Закрашивает область кистью: DC - дескриптор канвы окна; Rgn - дескриптор области; Brush - дескриптор кисти |
function FrameRgn(DC, Rgn,Brush: Cardinal; Width,Height: Integer): Bool; |
Обводит (но не заполняет) область кистью высотой Height и шириной Width пикселей |
function InvertRgn(DC, Rgn:Cardinal): Bool; |
Инвертирует все пиксели внутри области |
function OffsetRgn(DC, Rgn:Cardinal; dX, dY: Integer):Integer; |
Смещает область на dX по горизонтали и на dY по вертикали |
function PaintRgn(DC, Rgn:Cardinal): Bool; |
Закрашивает область текущей кистью
|
function PtInRegion(Rgn:Cardinal; X, Y: Integer):Bool; |
Проверяет принадлежность точки (X,Y) области Rgn |
function RectInRegion(Rgn:Cardinal; Rect: TRect):Bool; |
Проверяет принадлежность прямоугольника Rect области Rgn
|
function SetWindowRgn(DC,Rgn: Cardina; Redraw: Bool): Integer;
|
Показывает принадлежащую окну с канвой DC область Rgn вместо окна; Redraw- разрешает/запрещает перерисовку области; все не вошедшие в область части окна не показываются (см. ниже) |
Параметр combineMode в функции combineRgn может значения:
rgn_and - включает в результат общие части областей; rgn_copy -копирует область Rgnl В DestRgn; RGN_DIFF - исключает из Rgnl часть, принадлежащую Rgn2; rgn_or - объединяет области; rgn_xor -включает в результат только те части областей, которые не принадлежат им одновременно. Область DestRgn уже должна существовать и иметь размеры, достаточные для размещения объединенной области. При обращении к функции createPoiygonRgn параметр Poly FillMode может иметь значения: Alternate И Winding. В первом случае заполнение многоугольника идет последовательно между двумя близлежащими его сторонами: сначала между 1-й и 2-й, затем между 2-й и 3-й и т. д. В режиме winding заполняется все внутреннее пространство области.
Во всех случаях Windows автоматически проводит линию между последней и первой точкой многоугольника, делая его замкнутым.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
tуре
Tform1 = class(TForm)
PaintBoxl: TPaintBox;
PaintBox2: TPaintBox;
Button1: TButton;
procedure ButtonlClick(Sender: TObject);
private
{ Private declarations } public
{ Public declarations } end;
var
Form1: Tform1;
implernentation
$R *.DFM)
procedure TFormI.ButtonlClick(Sender: TObject);
var
Rgnl, Rgn2: Cardinal;
const
Points: array [1..5, 1..2] of Integer =
C(91, 0), (160, 183), (0, 70), (183, 70), (23, 183));
begin
Rgn1 := CreatePolygonRgn(Points, 5, Alternate);
Rgn2 := CreatePolygonRgn(Points, 5, Winding);
with PaintBoxl.Canvas do begin
Brush.Color := clBlack;
FillRgn(Handle, Rgnl, Brush.Handle);
end;
with PaintBox2.Canvas do begin
Brush.Color := clBlack;
FillRgn(Handle, Rgn2, Brush.Handle) ;
end;
end;
end.
Обратите внимание: прорисовка и объединение областей доступны, только если области видны в окне (для создания предыдущего рисунка нельзя, например, использовать обработчик формы OnActivate).
Функция SetWindowRgn, как уже отмечалось, поручает прорисовку окна самой Windows, при этом фактически прорисовывается не область, а лишь та часть окна, которая ограничена ею. Любые заливки области, ее очерчивание и объединение с другими областями игнорируются.
16.4.5. Классы TGraphic и TPicture
Важное место в графическом инструментарии Delphi занимают классы TGraphic и TPicture.
TGraphic - это абстрактный класс, инкапсулирующий общие свойства и методы трех своих потомков: пиктограммы (TIcon), метафайла (TMetafile) и растрового изображения (TBitmap). Общей особенностью потомков TGraphic является то, что обычно они сохраняются в файлах определенного формата. Пиктограммы представляют собой небольшие растровые изображения, снабженные специальными средствами, регулирующими их прозрачность. Для файлов пиктограмм обычно используется расширение ico. Метафайл - это изображение, построенное на графическом устройстве с помощью специальных команд, которые сохраняются в файле с расширением wmf или emf. Растровые изображения - это произвольные графические изображения в файлах со стандартным расширением bmp.
Свойства класса TGraphic:
property Empty: Boolean; |
Содержит True, если с объектом не связано графическое изображение |
property Height: Integer; |
Содержит высоту изображения в пикселях |
property Modified: Boolean; |
Содержит True, если графический объект изменялся |
property Palette: HPALETTE; |
Содержит цветовую палитру графического объекта |
property PaletteModified: Boolean; |
Содержит True, если менялась цветовая палитра графического объекта |
property Transparent: Boolean; |
Содержит True, если объект прозрачен для фона, на котором он изображен |
property Width: Integer; |
Содержит ширину изображения в пикселях |
Методы Класса TGraphic: |
|
procedure LoadFromClipooardFormat (AFormat: Word;AData: THandle; APalette:HPALETTE) ;
|
Ищет в буфере межпрограммного обмена Clipboard зарегистрированный формат AFormat и, если формат найден, загружает из буфера изображение AData и его палитру Apalette |
procedure LoadFromrile(const FileName:String) ; |
Загружает изображение из файла FileName |
procedure LoadFromStream(Stream: TStream); |
Загружает изображение из потока данных Stream |
procedure SaveToClipboardFormat (var AFormat: Word;var AData: THandle; varAPalette: HPALETTE); |
Помещает графическое изображение Adata и его цветовую палитру APalette в буфер межпрограммного обмена в формате Af ormat |
procedure SaveToFile(constFileName: Strings; |
Сохраняет изображение в файле FileName |
procedure SavePoStream(Stream: TStream); |
Сохраняет изображение в потоке Stream |
Полнофункциональный класс TPicture инкапсулирует в себе все необходимое для работы с готовыми графическими изображениями - пиктограммой, растром или метафайлом. Его свойство Graphic может содержать объект любого из этих типов, обеспечивая нужный полиморфизм методов класса.
Свойства класса TPicture:
property Bitmap: TBitmap; |
Интерпретирует графический объект как растровое изображение |
|
property Graphic: TGraphic; |
Содержит графический объект |
|
property Height: Integer; |
Содержит высоту изображения в пикселях |
|
property Icon: TIcon; |
Интерпретирует графический объект как пиктограмму |
|
property Metafile: TMetafile; |
Интерпретирует графический объект как метафайл |
|
property width: Integer; |
Содержит ширину изображения в пикселях |
Методы класса TPicture: |
procedure Assign(Source: TPersistent) ; |
Связывает собственный графический объект Graphic с объектом Source |
|
procedure LoadFromClipboardFormat (AFormat: Word;AData: THandle; APalette:HPALETTE) ; |
Ищет в буфере межпрограммного обмена Clipboard зарегистрированный формат AFormat и, если формат найден, загружает из буфера изображение AData и его палитру APalette |
|
procedure LoadFromFile(const FileName:String); |
Загружает изображение из файла FileName |
|
class procedure Register; ClipboardFormat(AFormat: Word; AGraphicClass: TGraphicClass) ; |
Используется для регистрации в Clipboard нового формата изображения
|
|
class procedure Register; FileFormat (const AExtension, ADescription: String; AGraphicClass: Tgraphic Class) ; |
Используется для регистрации нового файлового формата
|
|
class procedure RegisterFileFormatRes(const AExtension: String; ADescriptionResID: Integer; Agraphic Class: TGraphicClass); |
Используется для регистрации нового формата ресурсного файла |
|
procedure SaveToClipboardFormat (var AFormat: Word; var AData: THandle; varAPalette: HPALETTE); |
Помещает графическое изображение AData и его цветовую палитру APalette в буфер межпрограммного обмена в формате AFormat |
|
procedure SaveToFile(const FileName: Strings; |
Сохраняет изображение в файле FileName
|
|
class function SupportsClipboardFormat(AFormat: Word): Boolean; |
Возвращает True, если формат Aformat зарегистрирован в буфере межпрограммного обмена Clipboard |
|
class procedure UnregisterGraphicClass(AClass:TGraphicClass); |
Делает недоступными любые графические объекты класса Aclass |